import * as koa from 'koa2';
import * as cors from 'koa2-cors'
import * as Router from 'koa-router';
import crypto from '../utils/crypto';
import http from '../utils/http';
import { httpRouterMap } from '../configs_win';
import db from '../utils/db';
import Room_service from './room_service';
import Http from '../utils/http';
import Crypto from '../utils/crypto';






const callPth = 'hall_server -> client_service.ts ->';
const app = new koa();
const router = new Router();
let config: hall_server = null;


// 设置跨域
app.use(cors());
// 设置路由
app.use(router.routes()).use(router.allowedMethods());


export default class Client_service{
    /**
     * 开启大厅服务器 9001端口
     * @param _config 
     */
    static start(_config: hall_server){
        config = _config;
        app.listen(config.CLIENT_PORT, () => {
            console.log('大厅服务器运行在' + config.CLIENT_PORT + '端口');
        });
    }
}



router.get(httpRouterMap.LOGIN,                 login);
router.get(httpRouterMap.CREATE_USER,           create_user);
router.get(httpRouterMap.GET_USER_STATUS,       get_user_status);
router.get(httpRouterMap.GET_MESSAGE,           get_message);
router.get(httpRouterMap.CREATE_PRIVATE_ROOM,   create_private_room);
router.get(httpRouterMap.ENTER_PRIVATE_ROOM,    enter_private_room);













/**
 * 创建用户
 */
async function create_user(ctx: Router.IRouterContext) {
    if (!check_account(ctx)) {
        return;
    }

    const account = ctx.query.account;
    const name = ctx.query.name;
    const coins = 1000;
    const gems = 21;

    const isUserExist = await db.is_user_exist(account);
    if(isUserExist){
        http.send(ctx, 1, callPth + ctx.path + '->>错误信息：用户已经存在');
    }
    else{
        const flag = await db.create_user(account, name, coins, gems, 0, null);
        if(flag == 0){
            http.send(ctx, 0, 'ok');
        }
        else if(flag == 1){
            http.send(ctx, 2, callPth + ctx.path + '->>错误信息: 创建用户是的前4个参数里有为NULL的值');
        }
        else if(flag == 2){
            http.send(ctx, 2, callPth + ctx.path + '->错误信息: 创建用户时插入数据发生错误');
        }
    }
}


/**
 * 登录
 * @param ctx 
 */
async function login(ctx: Router.IRouterContext){
    if(!check_account(ctx)){
        return;
    }

    const ip = ctx.ip.includes('::ffff:') ? ctx.ip.substr(7) : ctx.ip;
    const account = ctx.query.account;
    const t_users_data1 = await db.get_user_data(account);
    if(t_users_data1 == null){
        http.send(ctx, 0, 'ok');
        return;
    }

    const ret: ret = {
        account: t_users_data1.account,
        userId: t_users_data1.userId,
        name: t_users_data1.name,
        lv: t_users_data1.lv,
        exp: t_users_data1.exp,
        coins: t_users_data1.coins,
        gems: t_users_data1.gems,
        ip: ip,
        sex: t_users_data1.sex || 1,
    };

    const roomId = await db.get_room_id_of_user(t_users_data1.userId);
    if(roomId){
        const room_is_running = await db.is_room_exist(roomId);
        if(room_is_running){
            ret.roomId = roomId;
        }
        else{
            // 如果房间不在了， 清楚数据库的roomId字段
            await db.set_room_id_of_user(t_users_data1.userId, null);
        }
    }
    http.send(ctx, 0, 'ok', ret);
}

/**
 * 使用account在t_users表中查找到gems信息并发送回去
 */
async function get_user_status(ctx: Router.IRouterContext){
    if (!check_account(ctx)) {
        return;
    }

    const account = ctx.query.account;
    const gems = await db.get_gems(account);
    if(gems){
        http.send(ctx, 0, 'ok', {gems});
    }
    else{
        http.send(ctx, 1, callPth + ctx.path + '->>错误信息： 超找用户的gems时出错！');
    }
}


/**
 * 获取公告信息及版本号
 */
async function get_message(ctx: Router.IRouterContext){
    if (!check_account(ctx)) {
        return;
    }

    const type = ctx.query.type;
    if(!type){
        http.send(ctx, -1, callPth + ctx.path + '->>错误信息： type属性为空，没法给你查公告及版本信息！');
        return;
    }

    const version = ctx.query.version;
    const data = await db.get_messgae(type, version);
    if(data){
        http.send(ctx, 0, 'ok', {msg: data.msg, version: data.version});
    }
    else{
        http.send(ctx, 1, callPth + ctx.path + '->>错误信息：查询信息及版本号是出错或没有查到，如果是第2种情况请检查参数是否正确');
    }
}

/**
 * 进入房间
 */
async function enter_private_room(ctx: Router.IRouterContext){
    const roomId = ctx.query.roomId;
    if(!roomId){
        http.send(ctx, 1, callPth + ctx.path + '->>错误信息：进入房间时没有roomId');
        return;
    }
    
    if (!check_account(ctx)) {
        return;
    }

    const account = ctx.query.account;
    const data = await db.get_user_data(account);
    if(!data){
        http.send(ctx, -1, callPth + ctx.path + '->>错误信息：进入房间时查询t_users表时没有数据或出错！');
        return;
    }
    
    const userId = data.userId;
    const name = data.name;
    const ret = await Room_service.enterRoom(userId, name, roomId);
    if (ret.errcode != 0) {
        ret.errmsg = callPth + 'enter_private_room()->' + ret.errmsg;
        Http.send(ctx, ret.errcode, ret.errmsg);
        return;
    }
    const retData: ret = {
        roomId: roomId,
        ip: ret.ip,
        port: ret.port,
        token: ret.token,
        time: Date.now(),
    }
    retData.sign = Crypto.md5(roomId + retData.token + retData.time + config.ROOM_PRI_KEY);
    Http.send(ctx, 0, 'ok', retData);
}

/**
 * 创建房间
 */
async function create_private_room(ctx: Router.IRouterContext){
    if (!check_account(ctx)) {
        return;
    }

    const account = ctx.query.account;
    const conf = ctx.query.conf;
    ctx.query.account = null;
    ctx.query.sign = null;

    const data = await db.get_user_data(account);
    if(!data){
        http.send(ctx, -1, callPth + ctx.path + '->>错误信息：创建房间时查询t_users表时没有数据或查询出错！');
        return;
    }

    const userId = data.userId;
    const name = data.name;
    let roomId = await db.get_room_id_of_user(userId);
    if(roomId){
        http.send(ctx, -1, callPth + ctx.path + '->>错误信息：创建房间时查询t_users表时有roomId，说明玩家还在玩耍中，应该返回房间而不是创建房间！');
        return; 
    }

    // 创建房间
    const data1 = await Room_service.createRoom(account, userId, conf);
    if(data1.errcode != 0){
        http.send(ctx, data1.errcode, ctx.path + data1.errmsg);
        return;
    }
    // 进入房间
    roomId = data1.roomId;
    const ret = await Room_service.enterRoom(userId, name, roomId);
    if(ret.errcode != 0){
        ret.errmsg = callPth + 'create_private_room()->' + ret.errmsg;
        Http.send(ctx, ret.errcode, ret.errmsg);
        return;
    }
    const retData: ret = {
        roomId: roomId,
        ip: ret.ip,
        port: ret.port,
        token: ret.token,
        time: Date.now(),
    }
    retData.sign = Crypto.md5(roomId + retData.token + retData.time + config.ROOM_PRI_KEY);
    Http.send(ctx, 0, 'ok', retData);
}


/**
 * 验证用户账号和签名是否存在
 */
function check_account(ctx: Router.IRouterContext){
    const account = ctx.query.account;
    const sign = ctx.query.sign;
    if(account == null && sign == null){
        http.send(ctx, 1, callPth + ctx.path + ' ->>错误信息：account或sign为空');
        return false;
    }
    return true;
}



